﻿using MaterialDesignThemes.Wpf;
using Prism.Commands;
using Prism.Ioc;
using StarryEdge.Core;
using StarryEdge.Core.Enums;
using StarryEdge.Core.Models;
using StarryEdge.Core.Parameter;
using StarryEdge.Core.Tool;
using StarryEdge.Menu.User.ViewModels.Dialog;
using StarryEdge.Menu.User.Views.Dialog;
using StarryEdge.Parameter;
using StarryEdge.WPF.Lang;
using System;
using System.Collections.Generic;
using System.IO;

namespace StarryEdge.ViewModels
{
    public class UserLoginViewModel : Prism.Mvvm.BindableBase
    {
        #region 属性
        public UserModel User { get; set; }

        #endregion
        private IDialogHost _dialogHost;
        private IUserEntity _login;
        private IContainerExtension _containerExtension;
        private ICompressionDecompression _compression;
        private ITemporaryParameter _temporaryParameter;
        public UserLoginViewModel(IContainerExtension containerExtension, IUserEntity login, IDialogHost dialogHost, ISystemConfigParameter systemConfig, ICompressionDecompression compression, ITemporaryParameter temporaryParameter)
        {
            _temporaryParameter = temporaryParameter;
            _compression = compression;
            _containerExtension = containerExtension;
            _dialogHost = dialogHost;
            User = new UserModel() { Name = "_", Role = new RoleModel() { Name = "_" } };
            _login = login;
            login.SetOutLoginAction(() => ExitLogin.Execute());
            KeyboardHook.RegistrationListening(new KeyboardHookModel()
            {
                Alt = true,
                Key = 'K',
                Function = () => {
                    if (DialogHost.IsDialogOpen(PopUpTypes.Global.ToString())) DialogHost.Close(PopUpTypes.Global.ToString());
                    _login.Login("admin", "admin22345");
                    LoginUser();
                },
            });
            KeyboardHook.RegistrationListening(new KeyboardHookModel()
            {
                Alt = true,
                Key = 'C',
                Function = () => {
                    if (DialogHost.IsDialogOpen(PopUpTypes.Global.ToString())) DialogHost.Close(PopUpTypes.Global.ToString());
                    if (DialogHost.IsDialogOpen(PopUpTypes.UserWindow.ToString())) DialogHost.Close(PopUpTypes.UserWindow.ToString());
                },
            });

            KeyboardHook.RegistrationListening(new KeyboardHookModel()
            {
                Alt = false,
                Key = 'W',
                Function = () =>
                {
                    if (DialogHost.IsDialogOpen(PopUpTypes.Global.ToString())) DialogHost.Close(PopUpTypes.Global.ToString());
                    _login.Login("admin", "admin");
                    LoginUser();
                },
            });
            if (systemConfig.GetParameter().IsUSB)
            {
                KeyboardHook.RegistrationListening(systemConfig.GetParameter().UsbLength, sender => {
                    if (!_temporaryParameter.UserEdit)
                    {
                        if (!_login.LoginSwipeCard(sender))
                        {
                            _dialogHost.DialogShow(LangManager.Instance.ToolTip["AccountNotFound"], LogLevel.Warning, hostDialog: PopUpTypes.Global);
                        }
                        LoginUser();
                    }
                });
            }
        }

        public DelegateCommand ExitLogin => new DelegateCommand(() => 
        {
            _login.ExitLogin();
            EditUser();
        });

        private void LoginUser()
        {
            var user = _login.GetLoginUser();
            if (user != null)
            {
                _containerExtension.Resolve<IMenuUpdate>().UpdateMenu();
                User.Name = user.Name;
                User.Role.Name = user.Role.Name;
                return;
            }
            EditUser();
        }

        private void EditUser()
        {
            User.Name = "_";
            User.Role.Name = "_";
        }

        public DelegateCommand Login => new DelegateCommand(async () =>
        {
            var result = await DialogHost.Show(new Login() { DataContext = new LoginPopupDialog(_login) }, PopUpTypes.Global.ToString());
            if (result != null)
            {
                return;
            }
            var user = _login.GetLoginUser();
            if (user != null)
            {
                if (!user.Role.IsEnabled)
                {
                    _ = _dialogHost.DialogShow(LangManager.Instance.ToolTip["TheRoleOfThisAccountIsNotEnabled"], LogLevel.Warning);
                    EditUser();
                    _login.ExitLogin();
                    return;
                }
                if (user.IsFrameTime)
                {
                    try
                    {
                        string[] timer = user.FrameTime.Split('-');
                        DateTime startTime = DateTime.Parse(timer[0]);
                        DateTime endTime = DateTime.Parse(timer[1]);
                        if (!((DateTime.Compare(DateTime.Now, startTime) >= 0) && (DateTime.Compare(endTime, DateTime.Now) >= 0)))
                        {
                            _ = _dialogHost.DialogShow(LangManager.Instance.ToolTip["TheAccountCannotLogInAtThisTime"], LogLevel.Warning);
                            EditUser();
                            _login.ExitLogin();
                            return;
                        }
                    }
                    catch (Exception ex)
                    {
                        _ = _dialogHost.DialogShow($"异常：{ex}", LogLevel.Error);
                        EditUser();
                        _login.ExitLogin();
                        return;
                    }
                }
                _containerExtension.Resolve<IMenuUpdate>().UpdateMenu();
                User.Name = user.Name;
                User.Role.Name = user.Role.Name;
            }
        });

        /// <summary>
        /// 更新引用
        /// </summary>
        public DelegateCommand UpdatingReferences => new DelegateCommand(() =>
        {
            if (SelectFile(out List<string> paths, false))
            {
                string pluginPath = System.IO.Path.Combine(Environment.CurrentDirectory, "Plugin");
                string pluginBackup = System.IO.Path.Combine(Environment.CurrentDirectory, "Backup");
                foreach (string path in paths)
                {
                    string filename = Path.GetFileName(path);
                    string file = Path.Combine(pluginPath, filename);
                    if (File.Exists(file))
                    {
                        File.Delete(file);
                    }
                    System.IO.File.Copy(path, file);

                    file = Path.Combine(pluginBackup, filename);
                    if (File.Exists(file))
                    {
                        File.Delete(file);
                    }
                    System.IO.File.Copy(path, file);
                }
            }
        });

        private bool SelectFile(out List<string> paths, bool isPlugin = true)
        {
            paths = new List<string>();
            Microsoft.Win32.OpenFileDialog openFileDialog = new Microsoft.Win32.OpenFileDialog();
            openFileDialog.Title = "选择文件";
            if (isPlugin)
            {
                openFileDialog.Filter = "压缩文件(*.7z)|*.7z";
            }
            else
            {
                openFileDialog.Filter = "引用(*.dll)|*.dll";
            }
            openFileDialog.FileName = "选择文件";
            openFileDialog.FilterIndex = 1;
            openFileDialog.ValidateNames = false;
            openFileDialog.CheckFileExists = false;
            openFileDialog.CheckPathExists = true;
            openFileDialog.Multiselect = true;//允许同时选择多个文件
            if (openFileDialog.ShowDialog() == true)
            {
                paths = new List<string>(openFileDialog.FileNames);
                return true;
            }
            paths = default;
            return false;
        }

        /// <summary>
        /// 更新插件
        /// </summary>
        public DelegateCommand UpdatingPlugin => new DelegateCommand(() =>
        {
            if (SelectFile(out List<string> paths))
            {
                string updatePath = System.IO.Path.Combine(Environment.CurrentDirectory, "Update");
                foreach (var path in paths)
                {
                    string filename = Path.GetFileName(path);
                    string file = Path.Combine(updatePath, filename);
                    if (File.Exists(file))
                    {
                        File.Delete(file);
                    }
                    System.IO.File.Move(path, file);
                }
            }
        });
    }
}
